import { ensureDir, expandGlob } from "https://deno.land/std@0.88.0/fs/mod.ts";
import * as path from "https://deno.land/std@0.88.0/path/mod.ts";
import { execCmd } from "https://deno.land/x/utils_ex@v0.0.2/mod.ts";

async function getFileList() {
  const files: string[] = [];
  const glob = expandGlob("./input/**/*.{mp4,MP4,flv,FLV,avi,AVI,wmv,WMV,mkv,MKV,swf,SWF,mov,MOV}");
  for await (const file of glob) {
    files.push(file.path);
  }
  return files;
}

function changeExt(path: string, newExtName: string) {
  return path.replace(/\.\w*$/, "." + newExtName);
}

const frameRate = ["-r", "24"];

// encoder
const x264 = ["-vcodec", "libx264", "-crf", "30"];
const h264N = ["-vcodec", "h264_nvenc", "-cq", "30"];
const x265 = ["-vcodec", "libx265", "-crf", "30"];
const h265N = ["-vcodec", "hevc_nvenc", "-cq", "32"];

// decoder
const h264decoderN = ["-c:v", "h264_cuvid"];

// audio
const aac = ["-acodec", "aac"];

async function transform(files: string[], fileIndex: number) {
  const inputFile = files[fileIndex];
  const outputFile = changeExt(files[fileIndex], "mp4").replace(
    "input",
    "output",
  );

  const dir = path.dirname(outputFile);
  await ensureDir(dir);
  const params = [
    "-y",
    "-i",
    inputFile,
    ...x264,
    ...aac,
    // ...frameRate,
    "-preset",
    "slow",
    "-tune",
    "stillimage",
    "-max_muxing_queue_size",
    "9999",
    outputFile,
  ];

  const inputReg = /Input.*from '(.*)'/;
  const durationReg = /Duration: (\d+:\d+:\d+.\d+)/;
  const timeAndSpeedReg = /time=(\d+:\d+:\d+.\d+).*speed=(\d+.\d+x)/;

  let inputStr = '';
  let durationStr = '';
  await execCmd(["ffmpeg", ...params], {
    stderr: str => {
      const input = str.match(inputReg)?.[1];
      const duration = str.match(durationReg)?.[1];
      const timeAndSpeed = str.match(timeAndSpeedReg);
      const time = timeAndSpeed?.[1];
      const speed = timeAndSpeed?.[2];
      if (input) {
        inputStr = input;
      }
      if (duration) {
        durationStr = duration;
      }
      if (time && speed) {
        console.info(`${fileIndex}/${files.length} # ${inputStr} # ${time}/${durationStr} # ${speed}`);
      }
    }
  })

  if (fileIndex + 1 < files.length) {
    await transform(files, fileIndex + 1);
  }
}

const files = await getFileList();
console.log(files);
if (files.length) {
  await transform(files, 0);
}
